using System;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Xml;
using System.Diagnostics;
using System.ComponentModel;

namespace Inikus.WinTimer
{
    /// <summary>
    /// Holds standard methods and classes for WinTimer
    /// </summary>
    public class TimerLibrary
    {
        #region IdleTime

        [System.Runtime.InteropServices.DllImport("User32.dll")]
        private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        internal struct LASTINPUTINFO
        {
            public uint cbSize;
            public uint dwTime;
        }

        public static uint GetIdleTime()
        {
            LASTINPUTINFO lastInPut = new LASTINPUTINFO();
            lastInPut.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(lastInPut);
            GetLastInputInfo(ref lastInPut);

            return ((uint)Environment.TickCount - lastInPut.dwTime);
        }

        #endregion

        #region Serialization

        /// <summary>
        /// Method to convert an Object to XML string
        /// </summary>
        /// <param name="pObject">Object that is to be serialized to XML</param>
        /// <returns>XML string</returns>
        private String SerializeObject(Object pObject, Type type)
        {
            try
            {
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer xs = new XmlSerializer(type);
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

                xs.Serialize(xmlTextWriter, pObject);
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                return UTF8ByteArrayToString(memoryStream.ToArray());
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return null;
            }
        }

        /// <summary>
        /// Method to reconstruct an Object from XML string
        /// </summary>
        /// <param name="pXmlizedString"></param>
        /// <returns></returns>
        public Object DeserializeObject(String pXmlizedString, Type type)
        {
            XmlSerializer xs = new XmlSerializer(type);
            MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString));
            XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

            return xs.Deserialize(memoryStream);
        }

        /// <summary>
        /// To convert a Byte Array of Unicode values (UTF-8 encoded) to a complete String.
        /// </summary>
        /// <param name="characters">Unicode Byte Array to be converted to String</param>
        /// <returns>String converted from Unicode Byte Array</returns>
        private static String UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            String constructedString = encoding.GetString(characters);
            return (constructedString);
        }

        /// <summary>
        /// Converts the String to UTF8 Byte array and is used in De serialization
        /// </summary>
        /// <param name="pXmlString"></param>
        /// <returns></returns>
        private static Byte[] StringToUTF8ByteArray(String pXmlString)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] byteArray = encoding.GetBytes(pXmlString);
            return byteArray;
        }

        #endregion
    }


    public class TimeCounter
    {
        #region Declarations

        private readonly DateTime _Date;
        private readonly DateTime _StartTime;

        // Measures times

        private Guid _Task;

        #endregion

        #region Constructor

        public TimeCounter()
        {
            Name = string.Empty;
            _Date = DateTime.Today;
            _StartTime = DateTime.Now;
            _Task = Guid.Empty;
            ActiveTime = TimeSpan.Zero;
            IdleTime = TimeSpan.Zero;
        }

        #endregion

        #region Properties

        public string Name { get; set; }

        public DateTime Date
        {
            get { return _Date; }
        }

        public DateTime StartTime
        {
            get { return _StartTime; }
        }

        public TimeSpan ActiveTime { get; set; }

        public TimeSpan IdleTime { get; set; }

        public string Comment { get; set; }

        public bool CurrentlyActive { get; private set; }

        #endregion

        #region Methods

        public void AddActiveTime(TimeSpan time)
        {
            ActiveTime = ActiveTime.Add(time);
            CurrentlyActive = true;
        }

        public void AddActiveTime(double milliseconds)
        {
            AddActiveTime(TimeSpan.FromMilliseconds(milliseconds));
        }

        public void AddIdleTime(TimeSpan time)
        {
            IdleTime = IdleTime.Add(time);
            CurrentlyActive = false;
        }

        public void AddIdleTime(double milliseconds)
        {
            AddIdleTime(TimeSpan.FromMilliseconds(milliseconds));
        }

        #endregion
    }
    
    public class InstanceControl : Component
    {
        private readonly string stProcName;
        /*constructor which holds the application name*/
        public InstanceControl(string ProcName)
        {
            stProcName = ProcName;
        }
        public bool InstanceExists()
        {  /*process class GetProcessesByName() checks for particular
            process is currently running and returns array of processes
            with that name*/
            Process[] processes = Process.GetProcessesByName(stProcName);

            return (processes.Length > 1);
        }
    }
}